home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * *
- * MODULE : betedit.cpp *
- * *
- * Purpose: Provides dialog controls derived from CEdit that validate *
- * the data entered with a minimum of help from the dialog *
- * containing the control. *
- * *
- * Comments: These classes were developed starting with the DATAVAL *
- * example code produced by Sara Williams of MicroSoft. *
- * *
- * History: Date Reason *
- * -------- ----------------------------------- *
- * *
- * 15/07/92 First version, provides CLongEdit and CRealEdit *
- * *
- **************************************************************************/
-
-
- #include <afxwin.h> // All the standard MFC stuff
- #include "betedit.h"
-
- #pragma warning(disable: 4100) // Disable "Unused formal parameter" warning
-
-
- /**************************************************************************
- * *
- * CLASS : CLongEdit *
- * *
- * Purpose: Provides a dialog control for long values that validates *
- * the data entered with a minimum of help from the dialog *
- * containing the control. *
- * *
- * Comments: *
- * *
- * History: Date Reason *
- * -------- ----------------------------------- *
- * *
- * 15/07/92 Created *
- * *
- **************************************************************************/
-
-
- BEGIN_MESSAGE_MAP(CLongEdit, CEdit)
- ON_WM_CHAR()
- ON_WM_KILLFOCUS()
- ON_MESSAGE(BEM_VALIDATE, OnValidate)
- END_MESSAGE_MAP()
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Constructor without parameters - set member variables to defaults
- //
- CLongEdit::CLongEdit()
- {
- m_lValue = 0;
- m_lMax = 100000;
- m_lMin = -100000;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Destructor
- //
- CLongEdit::~CLongEdit()
- {
- CEdit::~CEdit(); // Call base class destructor, but do nowt else
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Creating from C++ code - Create Windows object to connect to C++ object,
- // set position, style etc.
- //
- BOOL CLongEdit::Create(DWORD dwStyle, const RECT& rect,
- CWnd* pParentWnd, UINT nID)
- {
- return CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Aliasing on top of an existing Edit control
- //
- BOOL CLongEdit::SubclassEdit(UINT nID, CWnd* pParent, LONG lMin, LONG lMax)
- {
- m_lMin = lMin;
- m_lMax = lMax;
- m_lValue = 0;
- HWND hWndEdit = ::GetDlgItem(pParent->m_hWnd, nID);
- if (hWndEdit == NULL)
- return FALSE;
- return SubclassWindow(hWndEdit);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Set up text to reflect current value - this member function is intended
- // to be used internally, but it might prove valuable ...
- //
- void CLongEdit::RefreshText()
- {
- char szBuf[20];
-
- wsprintf(szBuf, "%ld", m_lValue);
- SetWindowText((LPSTR)szBuf); // Set text to match the value
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // SetRange : set the allowed limits and recheck the value
- //
- BOOL CLongEdit::SetRange(LONG lMin, LONG lMax)
- {
- m_lMin = lMin; // update the range info
- m_lMax = lMax;
- SetValue(m_lValue); // This will check value against limits
- return TRUE;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // SetValue : Define current value after checks
- //
- void CLongEdit::SetValue(LONG lVal)
- {
- if (lVal > m_lMax) lVal = m_lMax; // Limit using allowed range
- if (lVal < m_lMin) lVal = m_lMin;
- m_lValue = lVal;
- RefreshText(); // Get the text correct
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GetValue : return current value
- //
- LONG CLongEdit::GetValue()
- {
- Validate(FALSE); // Ensure that current value is up to date
- return m_lValue;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // User defined message: check our value against range. If wParam is zero
- // the check is done silently, without error messages, otherwise an error
- // message is generated. lParam is not used.
- //
- afx_msg LONG CLongEdit::OnValidate(UINT uShow, LONG lParam)
- {
- if (Validate((BOOL)uShow))
- return 1;
- else
- return 0;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Test the data : check our value against range. If bShow is FALSE
- // the check is done silently, without error messages, otherwise an error
- // message is generated.
- //
- BOOL CLongEdit::Validate(BOOL bShow)
- {
- char szBuf[60];
- char szBuffer[60];
- int num;
- LONG lTry;
-
- num = GetLine(0, (LPSTR)szBuf, 55); // Get our text in a string
- szBuf[num] = 0; // because GetLine does not insert null terminator
- num = sscanf(szBuf, "%Fld", (LPLONG)&lTry); // Get value as long
- if (num >= 0) // If conversion succeeded
- {
- if ((lTry >= m_lMin) && (lTry <= m_lMax)) // Check range
- { // Success, data can be accepted
- m_lValue = lTry; // Update current value
- RefreshText(); // Get the text neat
- return TRUE; // Return value sez all OK
- }
- else // Here for number out of range
- {
- if (bShow)
- {
- wsprintf(szBuffer, "Allowed range is %ld to %ld",
- m_lMin, m_lMax);
- GetParent()->MessageBox(szBuffer,
- "Entry rejected - out of range", MB_OK);
- }
- return FALSE; // Return value for failure
- }
- }
- else // Here for failed conversion to number
- {
- if (bShow)
- {
- wsprintf(szBuffer, "Numeric parseing failed %d", num);
- GetParent()->MessageBox(szBuffer,
- "Entry rejected - bad data", MB_OK);
- }
- return FALSE; // Return value for failure
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnKillFocus : Test on loss of focus
- // If data invalid, post a message to the dialog box proc to cause error
- // message and restore the focus to this control. Don't forget to pass
- // the message on down to the base CEdit class or you're dead.
- //
- afx_msg void CLongEdit::OnKillFocus(CWnd* pWnd)
- {
- if (!Validate(FALSE)) // If the data is invalid
- GetParent()->PostMessage(BEM_NOTVALID, GetDlgCtrlID(), 0);
- CEdit::OnKillFocus(pWnd); // Must pass this down to base class !
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Input character filter
- // Throw away all non-numeric characters. We allow '0' to '9', '-' and < 0x20
- //
- afx_msg void CLongEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- BOOL bOk;
-
- bOk = ((nChar < 0x20) || ((nChar >= '0') && (nChar <= '9')) ||
- (nChar == '-'));
- if (bOk)
- {
- CEdit::OnChar(nChar, nRepCnt, nFlags); // permitted
- }
- else
- {
- OnBadInput(); // illegal character - inform parent
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // default bad input handler, beep (unless parent notification
- // returns -1. Most parent dialogs will return 0 or 1 for command
- // handlers (i.e. Beep is the default)
- //
- void CLongEdit::OnBadInput()
- {
- if (GetParent()->SendMessage(WM_COMMAND,
- GetDlgCtrlID(), MAKELONG(m_hWnd, BEN_ILLEGALCHAR)) != -1)
- {
- MessageBeep(-1);
- }
- }
-
-
- /**************************************************************************
- * *
- * CLASS : CRealEdit *
- * *
- * Purpose: Provides a dialog control for real values that validates *
- * the data entered with a minimum of help from the dialog *
- * containing the control. *
- * *
- * Comments: *
- * *
- * History: Date Reason *
- * -------- ----------------------------------- *
- * *
- * 15/07/92 Created *
- * *
- **************************************************************************/
-
-
- BEGIN_MESSAGE_MAP(CRealEdit, CEdit)
- ON_WM_CHAR()
- ON_WM_KILLFOCUS()
- ON_MESSAGE(BEM_VALIDATE, OnValidate)
- END_MESSAGE_MAP()
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Constructor without parameters - set member variables to defaults
- //
- CRealEdit::CRealEdit()
- {
- m_fValue = 0;
- m_fMax = 100000;
- m_fMin = -100000;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Destructor
- //
- CRealEdit::~CRealEdit()
- {
- CEdit::~CEdit(); // Call base class destructor, but do nowt else
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Creating from C++ code - Create Windows object to connect to C++ object,
- // set position, style etc.
- //
- BOOL CRealEdit::Create(DWORD dwStyle, const RECT& rect,
- CWnd* pParentWnd, UINT nID)
- {
- if (CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID))
- {
- return TRUE;
- }
- else
- return FALSE;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Aliasing on top of an existing Edit control
- //
- BOOL CRealEdit::SubclassEdit(UINT nID, CWnd* pParent, float fMin, float fMax)
- {
- m_fMin = fMin;
- m_fMax = fMax;
- m_fValue = 0;
- HWND hWndEdit = ::GetDlgItem(pParent->m_hWnd, nID);
- if (hWndEdit == NULL)
- return FALSE;
- return SubclassWindow(hWndEdit);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Set up text to reflect current value.
- //
- void CRealEdit::RefreshText()
- {
- char szBuf[20];
-
- sprintf(szBuf, "%g", m_fValue);
- SetWindowText((LPSTR)szBuf); // Set text to match the value
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // SetRange : set the allowed limits and recheck the value
- //
- BOOL CRealEdit::SetRange(float fMin, float fMax)
- {
- m_fMin = fMin; // update the range info
- m_fMax = fMax;
- SetValue(m_fValue); // This will check value against limits
- return TRUE;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // SetValue : Define current value after checks
- //
- void CRealEdit::SetValue(float fVal)
- {
- if (fVal > m_fMax) fVal = m_fMax; // Limit using allowed range
- if (fVal < m_fMin) fVal = m_fMin;
- m_fValue = fVal;
- RefreshText(); // Get the text correct
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GetValue : return current value
- //
- float CRealEdit::GetValue()
- {
- Validate(FALSE); // Ensure that current value is up to date
- return m_fValue;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // User defined message: check our value against range. If wParam is zero
- // the check is done silently, without error messages, otherwise an error
- // message is generated. lParam is not used.
- //
- afx_msg LONG CRealEdit::OnValidate(UINT uShow, LONG lParam)
- {
- if (Validate((BOOL)uShow))
- return 1;
- else
- return 0;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Test the data : check our value against range. If bShow is FALSE
- // the check is done silently, without error messages, otherwise an error
- // message is generated.
- //
- BOOL CRealEdit::Validate(BOOL bShow)
- {
- char szBuf[60];
- char szBuffer[60];
- int num;
- float fTry;
-
- num = GetLine(0, (LPSTR)szBuf, 55); // Get our text in a string
- szBuf[num] = 0; // because GetLine does not insert null terminator
- num = sscanf(szBuf, "%Ff", (float __far *)&fTry); // Get value as float
- if (num >= 0) // If conversion succeeded
- {
- if ((fTry >= m_fMin) && (fTry <= m_fMax)) // Check range
- { // Success, data can be accepted
- m_fValue = fTry; // Update current value
- RefreshText(); // Get the text neat
- return TRUE; // Return value sez all OK
- }
- else // Here for number out of range
- {
- if (bShow)
- {
- sprintf(szBuffer, "Allowed range is %g to %g",
- m_fMin, m_fMax);
- GetParent()->MessageBox(szBuffer,
- "Entry rejected - out of range", MB_OK);
- }
- return FALSE; // Return value for failure
- }
- }
- else // Here for failed conversion to number
- {
- if (bShow)
- {
- wsprintf(szBuffer, "Numeric parseing failed %d", num);
- GetParent()->MessageBox(szBuffer,
- "Entry rejected - bad data", MB_OK);
- }
- return FALSE; // Return value for failure
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnKillFocus : Test on loss of focus
- // If data invalid, post a message to the dialog box proc to cause error
- // message and restore the focus to this control. Don't forget to pass
- // the message on down to the base CEdit class or you're dead.
- //
- afx_msg void CRealEdit::OnKillFocus(CWnd* pWnd)
- {
- if (!Validate(FALSE)) // If the data is invalid
- GetParent()->PostMessage(BEM_NOTVALID, GetDlgCtrlID(), 0);
- CEdit::OnKillFocus(pWnd); // Must pass this down to base class !
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Input character filter
- // Throw away all non-float characters. We allow '0' to '9',
- // '-', '.', 'E' and < 0x20
- //
- afx_msg void CRealEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- BOOL bOk;
-
- bOk = ((nChar < 0x20) || ((nChar >= '0') && (nChar <= '9')) ||
- (nChar == '-') || (nChar == '.') || (nChar == 'E'));
- if (bOk)
- {
- CEdit::OnChar(nChar, nRepCnt, nFlags); // permitted
- }
- else
- {
- OnBadInput(); // illegal character - inform parent
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // default bad input handler, beep (unless parent notification
- // returns -1. Most parent dialogs will return 0 or 1 for command
- // handlers (i.e. Beep is the default)
- //
- void CRealEdit::OnBadInput()
- {
- if (GetParent()->SendMessage(WM_COMMAND,
- GetDlgCtrlID(), MAKELONG(m_hWnd, BEN_ILLEGALCHAR)) != -1)
- {
- MessageBeep(-1);
- }
- }